# -*- coding:utf-8 -*-

## =====================================================================
## Copyright (C) 2007-2011  Jean-Philippe GOLAY
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2 of the License, or
## (at your option) any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the Free Software
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
## =====================================================================


from Tkinter import *
import Pmw
from tkMessageBox import *

from Persistance import *
from iNotes import NotesGUI
from iFamily import ProductFamilyListGUI
from iPlace import PlaceListGUI
from iReference import ReferenceListGUI
from iItem import ItemListGUI, Item

class ProductGUI(Toplevel):
	def __init__(self, parent=None, balloon=None, path=None, log=None):
		Toplevel.__init__(self, parent)
		self.parent=parent
		self.grab_set()
		self.transient(self.master)
		self.resizable(width=False, height=False)
		self.title(u"Produit")
		self.balloon=balloon
		self.imgLinks=PhotoImage(file="img/links_icon.gif")
		self.imgSearch=PhotoImage(file="img/search_icon.gif")
		self.imgNotes=PhotoImage(file="img/edit.gif")
		self.imgSave=PhotoImage(file="img/save_icon.gif")
		self.imgDelete=PhotoImage(file="img/delete_icon.gif")
		self.path=path
		self.log=log
		# Afficher un icon personnalisé
		try:
			if os.name =="posix":
				img = PhotoImage(file=self.path+"/icons/Product-icon.gif")
				self.tk.call("wm", "iconphoto", self._w, img)
			else:
				self.iconbitmap(default=self.path+"/icons/Product-icon.gif")
		except TclError:
			self.log.warning("Le window manager ne supporte pas l'icône que je veux lui mettre...")
		self.log.info("\tProductGUI\tStart")
		self.makeProduct()

	 # DEBUT de la gestion du module Product ------------------------------------------------------------------------------------------------------------
	def clearFieldProduct(self):
		# Mise a zéro des champs
		self.productValues[0].set("")
		self.productValues[1].set("")
		self.productValues[2].set("")
		self.productValues[3].set("")
		self.productValues[4].set("")
		self.productValues[5].set("0")
		self.productValues[6].set("2")
		self.productValues[7].set("0")
		self.productValues[8].set("1")
		self.productValues[9].set("")
		self.productValues[10].set("S")
		self.productValues[11].set("")
		self.productValues[12].set("")
		# Remise à zéro des ComboBox
		self.productStatusCB.selectitem(0)
		# des-activation du bouton Documents rattaché
		self.productDocBt.config(state=DISABLED)
		self.productItemProductBt.config(state=DISABLED)
		self.listObject=[ProductFamily, Place, Reference, Product]

	def selectProduct(self, event):
		if self.listProduct.get(0)!="":
			result = Product.select(Product.q.id==self.idListProduct[int(self.listProduct.curselection()[0])])
			for row in result:
				self.selectedProduct = row
			self.listObject[0]=self.selectedProduct.productFamily
			self.listObject[1]=self.selectedProduct.place
			self.listObject[2]=self.selectedProduct.reference
			self.listObject[3]=self.selectedProduct
			self.productValues[0].set(self.listObject[0].designation)
			self.productValues[1].set(self.listObject[1].company)
			self.productValues[2].set(self.listObject[2].code)
			if self.selectedProduct.designation != None:self.productValues[3].set(self.selectedProduct.designation)
			if self.selectedProduct.description != None:self.productValues[4].set(self.selectedProduct.description)
			if self.selectedProduct.number != None:self.productValues[5].set(self.selectedProduct.number)
			if self.selectedProduct.sleeps != None:self.productValues[6].set(str(self.selectedProduct.sleeps))
			if self.selectedProduct.area != None:self.productValues[7].set(str(self.selectedProduct.area))
			if self.selectedProduct.floor != None:self.productValues[8].set(str(self.selectedProduct.floor))
			if self.selectedProduct.tel != None:self.productValues[9].set(self.selectedProduct.tel)
			if self.selectedProduct.status != None:self.productValues[10].set(self.selectedProduct.status)
			# Affichage du Type dans la ComboBox
			status = (("S", 0),("A", 1),("P", 2),("I", 3),("T", 4),("M", 5),("F", 6),)
			for n in status:
				if n[0] == self.selectedProduct.status: self.productStatusCB.selectitem(n[1])
			# Affichage de la présence de documents lié a ce produit
			result = ProductPhoto.select(ProductPhoto.q.product==self.selectedProduct)
			count=0
			for row in result:
				count+=1
			if count < 2:
				self.productValues[11].set(str(count)+" Document")
			else:
				self.productValues[11].set(str(count)+" Documents")
			 # Affichage de la présence d'Articles lié a ce produit
			result = ProductItem.select(ProductItem.q.product==self.selectedProduct)
			count=0
			for row in result:
				count+=1
			if count < 2:
				self.productValues[12].set(str(count)+" Article")
			else:
				self.productValues[12].set(str(count)+" Articles")
			# activation des boutons Documents et Articles rattachés
			self.productDocBt.config(state=NORMAL)
			self.productItemProductBt.config(state=NORMAL)
			# activation du bouton supprimer
			self.deleteProductBt.config(state=NORMAL)

	def searchProduct(self, event=None):
		if self.searchProductValue.get() != "":
			self.listProduct.delete(0,END)
			self.idListProduct = []
			result = Product.select(Product.q.designation.startswith(self.searchProductValue.get().encode("utf-8")), orderBy=Product.q.designation)
			for row in result:
				self.listProduct.insert(END, row.place.company+" - "+str(row.number)+" - "+row.designation)
				self.idListProduct.append(row.id)
		else:
			self.listProduct.delete(0,END)
			self.idListProduct = []
			result = Product.select(orderBy=Product.q.designation)
			for row in result:
				self.listProduct.insert(END, row.place.company+" - "+str(row.number)+" - "+row.designation)
				self.idListProduct.append(row.id)

	def makeProduct(self):
		leftFrame = Frame(self)
		# Fiche Service  (présentation colonne de gauche)
		Label(leftFrame, text=u"Produit").pack(side=TOP, fill=X)
		# Création des champs a renseigner pour un object Product
		productStatusListCB=("Sale", "A verifier", "Propre", "Intervention", "Traveaux", "Maintennance", "Fermer")
		productLabels = (u"Famille", u"Résidence", u"Référence", u"Désignation", u"Déscription", u"Numèro", u"Couchage", u"Surface", u"Etage", u"Tél", u"Status", u"Documents", u"Articles")
		self.productValues = [StringVar(), StringVar(), StringVar(), StringVar(), StringVar(), StringVar(), StringVar(), StringVar(), StringVar(), StringVar(), StringVar(), StringVar(), StringVar()]
		count = 0
		for name in productLabels:
			f = Frame(leftFrame)
			Label(f, width=12, text=name, anchor=W).pack(side=LEFT)
			if count == 0: # Famille de Product
				Entry(f, textvariable=self.productValues[count], width=21, state=DISABLED, bd=0, disabledforeground="black").pack(side=LEFT, fill=X)
				myFamilyProduct=Button(f,  image=self.imgSearch, command=lambda x=self.productValues[count]:self.ctrlListProductFamily(x),  padx=4, pady=1)
				myFamilyProduct.pack(side=RIGHT)
				self.balloon.bind(myFamilyProduct, u"Choisir une Famille de Produit")
			elif count == 1: # Résidence
				Entry(f, textvariable=self.productValues[count], width=21, state=DISABLED, bd=0, disabledforeground="black").pack(side=LEFT, fill=X)
				myPlace=Button(f,  image=self.imgSearch, command=lambda x=self.productValues[count]:self.ctrlListPlace(x), padx=4, pady=1)
				myPlace.pack(side=RIGHT)
				self.balloon.bind(myPlace, u"Choisir une Résidence")
			elif count == 2: # Référence
				Entry(f, textvariable=self.productValues[count], width=21, state=DISABLED, bd=0, disabledforeground="black").pack(side=LEFT, fill=X)
				myReference=Button(f,  image=self.imgSearch, command=lambda x=self.productValues[count]:self.ctrlListReference(x),  padx=4, pady=1)
				myReference.pack(side=RIGHT)
				self.balloon.bind(myReference, u"Choisir une Référence")
			elif count == 4: # Déscription
				Entry(f, textvariable=self.productValues[count], width=21).pack(side=LEFT, fill=X)
				myDescription=Button(f,  image=self.imgNotes, command=lambda x=self.productValues[count]:self.ctrlNotes(x,u"Déscription du produit"),  padx=4, pady=1)
				myDescription.pack(side=RIGHT)
				self.balloon.bind(myDescription, u"Détails de la déscription")
			elif count == 10: # Status
				self.productStatusCB=Pmw.ComboBox(f, selectioncommand=self.productStatus, scrolledlist_items=productStatusListCB, listheight=100)
				self.productStatusCB.pack(side=LEFT, fill=X)
				self.productStatusCB._entryfield._entryFieldEntry.config( width = 21)
				self.productStatusCB.selectitem(0)
				self.productValues[count].set(u"S")
			elif count == 11: # Documents
				Entry(f, textvariable=self.productValues[count], width=21, state=DISABLED, bd=0, disabledforeground="black").pack(side=LEFT, fill=X)
				self.productDocBt=Button(f,  image=self.imgLinks, command=lambda x=self.productValues[count]:self.ctrlProductPhoto(x), padx=4, pady=1, state=DISABLED)
				self.balloon.bind(self.productDocBt, u"Ajouter ou suprimer des documents (photos) liés au produit.\nCommencer par créer un produit puis séléctionner le dans la\nliste pour pouvoir lui ajouter des documents liés.")
				self.productDocBt.pack(side=RIGHT)
			elif count == 12: # Articles rattacher
				Entry(f, textvariable=self.productValues[count], width=21, state=DISABLED, bd=0, disabledforeground="black").pack(side=LEFT, fill=X)
				self.productItemProductBt=Button(f,  image=self.imgLinks, command=lambda x=self.productValues[count]:self.ctrlProductItem(x), padx=4, pady=1, state=DISABLED)
				self.balloon.bind(self.productItemProductBt, u"Ajouter ou suprimer des Articles liés au produit.\nCommencer par créer un produit puis séléctionner le dans la\nliste pour pouvoir lui ajouter des documents liés.")
				self.productItemProductBt.pack(side=RIGHT)
			else: 
				Entry(f, textvariable=self.productValues[count], width=24, justify=RIGHT).pack(side=LEFT, fill=X)
			f.pack(side=TOP, fill=X)
			count += 1
		# Boutons enregistrement (new ou modify) et suppression
		s = Frame(leftFrame) 
		self.saveProductBt=Button(s, image=self.imgSave, command=self.createProduct)
		self.saveProductBt.bind("<Return>", self.createProduct)
		self.saveProductBt.pack(side=LEFT)
		self.balloon.bind(self.saveProductBt, u"Enregistrer")
		self.deleteProductBt=Button(s, image=self.imgDelete, command=self.deleteProduct, state=DISABLED)
		self.deleteProductBt.bind("<Return>", self.deleteProduct)
		self.deleteProductBt.pack(side=LEFT)
		self.balloon.bind(self.deleteProductBt, u"Supprimer")
		s.pack(side=TOP, fill=X)
		leftFrame.pack(side=LEFT, fill=X)
		# Liste des Product existants (présentation colonne de droite)
		rightFrame = Frame(self) 
		Label(rightFrame, text=u"Liste des Produits").pack(side=TOP, fill=X)
		self.searchProductValue = StringVar()
		self.searchProductEt = Entry(rightFrame,  width=63, textvariable=self.searchProductValue, relief=GROOVE)
		self.searchProductEt.bind("<KeyRelease>", self.searchProduct)
		self.searchProductEt.pack(side=TOP, fill=X)
		self.balloon.bind(self.searchProductEt, u"Saisir les premières lettres d'un Produit\npour une recherche plus précise,\nla liste est classée par désignation.")
		s = Frame(rightFrame) 
		scrollbar = Scrollbar(s)
		scrollbar.pack(side=RIGHT, fill=Y)
		self.listProduct = Listbox(s)
		self.listProduct.config(yscrollcommand=scrollbar.set, width=60, selectmode=SINGLE, height=16)
		self.listProduct.bind("<ButtonRelease-1>",self.selectProduct)
		scrollbar.config(command=self.listProduct.yview)
		self.listProduct.pack()
		self.balloon.bind(self.listProduct, u"Séléctionner un Produit\npour le visualiser ou la modifier.")
		s.pack(side=TOP, fill=X)
		rightFrame.pack(side=RIGHT, fill=BOTH)
		# Initialisation
		self.clearFieldProduct()
		self.searchProduct()

	def ctrlNotes(self,field,title):
		NotesGUI(field=field,title=title, log=self.log, path=self.path)

	def ctrlListPlace(self,field):
		PlaceListGUI(balloon=self.balloon, field=field, index=1, listObject=self.listObject, log=self.log, path=self.path)

	def ctrlListProductFamily(self,field):
		ProductFamilyListGUI(balloon=self.balloon, field=field, index=0, listObject=self.listObject, log=self.log, path=self.path)

	def ctrlListReference(self,field):
		ReferenceListGUI(balloon=self.balloon, field=field, index=2, listObject=self.listObject, log=self.log, path=self.path)

	def ctrlProductPhoto(self,field): # index 3
		ProductPhotoGUI(balloon=self.balloon, field=field, index=3, listObject=self.listObject, log=self.log, path=self.path)
		
	def ctrlProductItem(self,field): # index 3
		ProductItemGUI(balloon=self.balloon, field=field, index=3, listObject=self.listObject, log=self.log, path=self.path)

	def productStatus(self, value):
		status = (("S", "Sale"),("A", "A verifier"),("P", "Propre"),("I", "Intervention"),("T", "Traveaux"),("M", "Maintennance"),("F", "Fermer"),)
		for n in status:
			if n[1] == value: self.productValues[10].set(n[0])

	def verifyProduct(self):
		if self.productValues[0].get() == "":
			showerror(u"Erreur de saisie", u"Le champ Famille de Produit est obligatoire !\nMerci de le compléter.")
			return False
		elif self.productValues[1].get() == "":
			showerror(u"Erreur de saisie", u"Le champ Résidences est obligatoire !\nMerci de le compléter.")
			return False
		elif self.productValues[2].get() == "": 
			showerror(u"Erreur de saisie", u"Le champ Référence est obligatoire !\nMerci de le compléter.")
			return False
		elif self.productValues[3].get() == "": 
			showerror(u"Erreur de saisie", u"Le champ Désignation est obligatoire !\nMerci de le compléter.")
			return False
		elif self.productValues[5].get() == "": 
			showerror(u"Erreur de saisie", u"Le champ Numéro est obligatoire !\nMerci de le compléter.")
			return False
		else:
			# TODO Vérifier la validité des nombres (Integer) pour les champs de 6 à 8
			return True

	def createProduct(self, event=None):
		if self.verifyProduct():
			if  self.deleteProductBt.config()["state"][4] == "normal":
				self.modifyProduct()
			else:
				if askyesno(u"Enregistrement", u"Souhaitez-vous enregistrer %s comme un nouveau Produit ?\n" % self.productValues[7].get()):
					Product(productFamily=self.listObject[0],
						place=self.listObject[1],
						reference=self.listObject[2],
						designation=self.productValues[3].get().encode("utf-8"),
						description=self.productValues[4].get().encode("utf-8"),
						number=self.productValues[5].get(),
						sleeps=int(self.productValues[6].get()),
						area=int(self.productValues[7].get()),
						floor=int(self.productValues[8].get()),
						tel=self.productValues[9].get().encode("utf-8"),
						status=self.productValues[10].get().encode("utf-8"),
						createDate=datetime.datetime.now()
					)
					self.searchProduct()
				self.clearFieldProduct()

	def modifyProduct(self, event=None): 
		if askyesno(u"Modifier", u"Souhaitez-vous modifier le Produit %s ?" % self.selectedProduct.designation):
			self.selectedProduct.productFamily=self.listObject[0]
			self.selectedProduct.place=self.listObject[1]
			self.selectedProduct.reference=self.listObject[2]
			self.selectedProduct.designation=self.productValues[3].get().encode("utf-8")
			self.selectedProduct.description=self.productValues[4].get().encode("utf-8")
			self.selectedProduct.number=self.productValues[5].get()
			self.selectedProduct.sleeps=int(self.productValues[6].get())
			self.selectedProduct.area=int(self.productValues[7].get())
			self.selectedProduct.floor=int(self.productValues[8].get())
			self.selectedProduct.tel=self.productValues[9].get().encode("utf-8")
			self.selectedProduct.status=self.productValues[10].get().encode("utf-8")       
			self.searchProduct()
		self.deleteProductBt.config(state=DISABLED)
		self.clearFieldProduct()

	def deleteProduct(self, event=None): 
		if askyesno(u"Suppression", u"Souhaitez-vous supprimer le Produit %s ?\nCette opération est irréversible !" % self.selectedProduct.designation):
			Product.delete(self.selectedProduct.id)
			self.searchProduct()            
		self.deleteProductBt.config(state=DISABLED)
		self.clearFieldProduct()
	# FIN de la gestion du module Product ------------------------------------------------------------------------------------------------------------------

class ProductListGUI(Toplevel):
	def __init__(self, parent=None, balloon=None, field=None, index=None, indexPlace=None, listObject=None, path=None, log=None):
		Toplevel.__init__(self, parent)
		self.parent=parent
		self.grab_set()
		self.transient(self.master)
		self.resizable(width=False, height=False)
		self.title(u"Liste des Produits")
		self.balloon=balloon
		self.imgNew=PhotoImage(file="img/add_alternative_icon.gif")
		self.field=field
		self.index=index
		self.indexPlace=indexPlace
		self.listObject=listObject
		self.path=path
		self.log=log
		# Afficher un icon personnalisé
		try:
			if os.name =="posix":
				img = PhotoImage(file=self.path+"/icons/Product-icon.gif")
				self.tk.call("wm", "iconphoto", self._w, img)
			else:
				self.iconbitmap(default=self.path+"/icons/Product-icon.gif")
		except TclError:
			self.log.warning("Le window manager ne supporte pas l'icône que je veux lui mettre... tant pis")
		self.log.info("\tProductListGUI\tStart")
		self.makeListProduct()

	def selectListProduct(self, event):
		if self.listListProduct.get(0)!="":
			result = Product.select(Product.q.id==self.idListListProduct[int(self.listListProduct.curselection()[0])])
			for row in result:
				self.listObject[self.index]=row
				self.field.set(row.number+" - "+row.designation)
				self.destroy()

	def searchListProduct(self, event=None):
		if self.searchListProductValue.get() != "":
			self.listListProduct.delete(0,END)
			self.idListListProduct = []
			if self.indexPlace!=None and self.listObject[self.indexPlace] != Place:
				result = Product.select(AND(Product.q.designation.startswith(self.searchListProductValue.get().encode("utf-8")), Product.q.place==self.listObject[self.indexPlace]), orderBy=Product.q.number)
			else:
				result = Product.select(Product.q.designation.startswith(self.searchListProductValue.get().encode("utf-8")), orderBy=Product.q.number)
			for row in result:
				self.listListProduct.insert(END, row.number+" - "+row.designation+" - "+row.place.company)
				self.idListListProduct.append(row.id)
		else:
			self.listListProduct.delete(0,END)
			self.idListListProduct = []
			if self.indexPlace!=None and self.listObject[self.indexPlace] != Place:
				result = Product.select(Product.q.place==self.listObject[self.indexPlace], orderBy=Product.q.number)
			else:
				result = Product.select(orderBy=Product.q.number)
			for row in result:
				self.listListProduct.insert(END, row.number+" - "+row.designation+" - "+row.place.company)
				self.idListListProduct.append(row.id)

	def makeListProduct(self):
		leftFrame = Frame(self)
		Label(leftFrame, text=u"Liste des Produits").pack(side=TOP, fill=X)
		self.searchListProductValue = StringVar()
		s = Frame(leftFrame) 
		self.searchListProductEt = Entry(s,  width=39, textvariable=self.searchListProductValue, relief=GROOVE)
		self.searchListProductEt.bind("<KeyRelease>", self.searchListProduct)
		self.searchListProductEt.pack(side=LEFT, fill=X)
		self.balloon.bind(self.searchListProductEt, u"Saisir les premiéres lettres de la désignation d'un Produit\npour une recherche plus précise,\nla liste est classée par numéros.")
		newProductBt=Button(s, image=self.imgNew, command=self.ctrlProduct)
		newProductBt.pack(side=RIGHT)
		self.balloon.bind(newProductBt, u"Créer une nouveau Produit")
		s.pack(side=TOP, fill=X)
		s = Frame(leftFrame) 
		scrollbar = Scrollbar(s)
		scrollbar.pack(side=RIGHT, fill=Y)
		self.listListProduct = Listbox(s)
		self.listListProduct.config(yscrollcommand=scrollbar.set,width=40, selectmode=SINGLE, height=16)
		self.listListProduct.bind("<ButtonRelease-1>",self.selectListProduct)
		scrollbar.config(command=self.listListProduct.yview)
		self.listListProduct.pack(side=TOP, fill=X)
		self.balloon.bind(self.listListProduct, u"Séléctionner un Produit.")
		s.pack(side=TOP, fill=X)
		leftFrame.pack()
		self.searchListProduct()
		
	def ctrlProduct(self):
		ProductGUI(balloon=self.balloon, log=self.log, path=self.path)

class ProductPhotoGUI(Toplevel):
	def __init__(self, parent=None, balloon=None, field=None, index=None, listObject=None, path=None, log=None):
		Toplevel.__init__(self, parent)
		self.parent=parent
		self.grab_set()
		self.transient(self.master)
		self.resizable(width=False, height=False)
		self.balloon=balloon
		self.imgSave=PhotoImage(file="img/save_icon.gif")
		self.imgDelete=PhotoImage(file="img/delete_icon.gif")
		self.imgNotes=PhotoImage(file="img/edit.gif")
		self.field=field
		self.index=index
		self.listObject=listObject
		self.title(u"Documents associés")
		self.path=path
		self.log=log
		# Afficher un icon personnalisé
		try:
			if os.name =="posix":
				img = PhotoImage(file=self.path+"/icons/Product-icon.gif")
				self.tk.call("wm", "iconphoto", self._w, img)
			else:
				self.iconbitmap(default=self.path+"/icons/Product-icon.gif")
		except TclError:
			self.log.warning("Le window manager ne supporte pas l'icône que je veux lui mettre...")
		self.log.info("\tProductPhotoGUI\tStart")
		self.makeProductPhoto()

	# DEBUT de la gestion du module ProductPhoto --------------------------------------------------------------------------------------------------
	def clearFieldProductPhoto(self):
		# Mise a zéro des champs de la fiche
		self.productPhotoValues[1].set("")
		self.productPhotoValues[2].set("")
		self.productPhotoValues[3].set("")
		# Affichage de la présence de documents lié a ce produit
		result = ProductPhoto.select(ProductPhoto.q.product==self.listObject[self.index])
		count=0
		for row in result:
			count+=1
		if count < 2:
			self.field.set(str(count)+" Document")
		else:
			self.field.set(str(count)+" Documents")

	def selectProductPhoto(self, event):
		if self.listProductPhoto.get(0)!="":
			result = ProductPhoto.select(ProductPhoto.q.id==self.idListProductPhoto[int(self.listProductPhoto.curselection()[0])])
			for row in result:
				self.selectedProductPhoto = row
			if self.selectedProductPhoto.name != None:self.productPhotoValues[1].set(self.selectedProductPhoto.name)
			if self.selectedProductPhoto.img != None:self.productPhotoValues[2].set(self.selectedProductPhoto.img)
			if self.selectedProductPhoto.comment != None:self.productPhotoValues[3].set(self.selectedProductPhoto.comment)
			# activation du bouton supprimer
			self.deleteProductPhotoBt.config(state=NORMAL)

	def searchProductPhoto(self, event=None):
		if self.searchProductPhotoValue.get() != "":
			self.listProductPhoto.delete(0,END)
			self.idListProductPhoto = []
			result = ProductPhoto.select(AND(ProductPhoto.q.name.startswith(self.searchProductPhotoValue.get().encode("utf-8")), ProductPhoto.q.product==self.listObject[self.index]), orderBy=ProductPhoto.q.id)
			for row in result:
				self.listProductPhoto.insert(END, str(row.id)+" - "+row.name)
				self.idListProductPhoto.append(row.id)
		else:
			self.listProductPhoto.delete(0,END)
			self.idListProductPhoto = []
			result = ProductPhoto.select(ProductPhoto.q.product==self.listObject[self.index],orderBy=ProductPhoto.q.id)
			for row in result:
				self.listProductPhoto.insert(END, str(row.id)+" - "+row.name)
				self.idListProductPhoto.append(row.id)

	def makeProductPhoto(self):
		leftFrame = Frame(self)
		# Fiche Document  (présentation colonne de gauche)
		Label(leftFrame, text=u"Fiche Document").pack(side=TOP, fill=X)
		# Création des champs a renseigner pour un object ProductPhoto
		productPhotoLabels = (u"Produit", u"Nom", u"Chemin du document", u"Commentaires")
		self.productPhotoValues = [StringVar(), StringVar(), StringVar(), StringVar()]
		count = 0
		for name in productPhotoLabels:
			f = Frame(leftFrame)
			Label(f, width=16, text=name, anchor=W).pack(side=LEFT)
			if count == 0: # Product
				Entry(f, textvariable=self.productPhotoValues[count], width=21, state=DISABLED, bd=0, disabledforeground="black").pack(side=LEFT, fill=X)
			elif count == 3: # Commentaires
				Entry(f, textvariable=self.productPhotoValues[count], width=21).pack(side=LEFT, fill=X)
				myNotes=Button(f, image=self.imgNotes, command=lambda x=self.productPhotoValues[count]:self.ctrlNotes(x,u"Commentaires"), padx=4, pady=1)
				myNotes.pack(side=RIGHT)
				self.balloon.bind(myNotes, u"Détails de la note")
			else: 
				Entry(f, textvariable=self.productPhotoValues[count], width=24).pack(side=LEFT, fill=X)
			f.pack(side=TOP, fill=X)
			count += 1
		# Boutons enregistrement (new ou modify) et suppression
		s = Frame(leftFrame) 
		self.saveProductPhotoBt=Button(s, image=self.imgSave, command=self.createProductPhoto)
		self.saveProductPhotoBt.bind("<Return>", self.createProductPhoto)
		self.saveProductPhotoBt.pack(side=LEFT)
		self.balloon.bind(self.saveProductPhotoBt, u"Enregistrer")
		self.deleteProductPhotoBt=Button(s, image=self.imgDelete, command=self.deleteProductPhoto, state=DISABLED)
		self.deleteProductPhotoBt.bind("<Return>", self.deleteProductPhoto)
		self.deleteProductPhotoBt.pack(side=LEFT)
		self.balloon.bind(self.deleteProductPhotoBt, u"Supprimer")
		s.pack(side=TOP, fill=X)
		#~ leftFrame.pack(side=LEFT, fill=X)
		# Liste des Document existants (présentation colonne de droite)
		#~ rightFrame = Frame(self) 
		Label(leftFrame, text=u"Liste Documents liés à (ID:"+str(self.listObject[self.index].id)+") "+self.listObject[self.index].designation).pack(side=TOP, fill=X)
		self.searchProductPhotoValue = StringVar()
		self.searchProductPhotoEt = Entry(leftFrame,  width=43, state=DISABLED, textvariable=self.searchProductPhotoValue, relief=GROOVE)
		self.searchProductPhotoEt.bind("<KeyRelease>", self.searchProductPhoto)
		self.searchProductPhotoEt.pack(side=TOP, fill=X)
		self.balloon.bind(self.searchProductPhotoEt, u"Saisir les premières lettres d'un Document\npour une recherche plus précise,\nla liste est classée par nom.")
		s = Frame(leftFrame) 
		scrollbar = Scrollbar(s)
		scrollbar.pack(side=RIGHT, fill=Y)
		self.listProductPhoto = Listbox(s)
		self.listProductPhoto.config(yscrollcommand=scrollbar.set, width=40, selectmode=SINGLE, height=10)
		self.listProductPhoto.bind("<ButtonRelease-1>",self.selectProductPhoto)
		scrollbar.config(command=self.listProductPhoto.yview)
		self.listProductPhoto.pack(side=TOP, fill=X)
		self.balloon.bind(self.listProductPhoto, u"Séléctionner un Document\npour le visualiser ou la modifier.")
		s.pack(side=TOP, fill=X)
		#~ rightFrame.pack(side=RIGHT, fill=X)
		leftFrame.pack(side=LEFT, fill=X)
		# Initialisation
		self.productPhotoValues[0].set(self.listObject[self.index].designation)
		self.searchProductPhoto()

	def ctrlNotes(self,field,title):
		n=NotesGUI(field=field,title=title, log=self.log, path=self.path)

	def verifyProductPhoto(self):
		if self.productPhotoValues[0].get() == "":
			showerror(u"Erreur de saisie", u"Le champ Product est obligatoire !\nMerci de le compléter.")
			return False
		elif self.productPhotoValues[1].get() == "":
			showerror(u"Erreur de saisie", u"Le champ Nom est obligatoire !\nMerci de le compléter.")
			return False
		elif self.productPhotoValues[2].get() == "": 
			showerror(u"Erreur de saisie", u"Le champ Chemin est obligatoire !\nMerci de le compléter.")
			return False
		elif self.productPhotoValues[3].get() == "": 
			showerror(u"Erreur de saisie", u"Le champ Commentaire est obligatoire !\nMerci de le compléter.")
			return False
		else:
			return True

	def createProductPhoto(self, event=None):
		if self.verifyProductPhoto():
			if  self.deleteProductPhotoBt.config()["state"][4] == "normal":
				self.modifyProductPhoto()
			else:
				if askyesno(u"Enregistrement", u"Souhaitez-vous enregistrer %s comme un nouveau Document ?\n" % self.productPhotoValues[1].get()):
					ProductPhoto(product=self.listObject[self.index],
						name=self.productPhotoValues[1].get().encode("utf-8"),
						img=self.productPhotoValues[2].get().encode("utf-8"),
						comment=self.productPhotoValues[3].get().encode("utf-8"),
						createDate=datetime.datetime.now()
					)
					self.searchProductPhoto()
				self.clearFieldProductPhoto()

	def modifyProductPhoto(self, event=None): 
		if askyesno(u"Modifier", u"Souhaitez-vous modifier le Document %s ?" % self.selectedProductPhoto.name):
			self.selectedProductPhoto.name=self.productPhotoValues[1].get().encode("utf-8")
			self.selectedProductPhoto.img=self.productPhotoValues[2].get().encode("utf-8")
			self.selectedProductPhoto.comment=self.productPhotoValues[3].get().encode("utf-8")       
			self.searchProductPhoto()
		self.deleteProductPhotoBt.config(state=DISABLED)
		self.clearFieldProductPhoto()

	def deleteProductPhoto(self, event=None): 
		if askyesno(u"Suppression", u"Souhaitez-vous supprimer le Document %s ?\nCette opération est irréversible !" % self.selectedProductPhoto.name):
			ProductPhoto.delete(self.selectedProductPhoto.id)
			self.searchProductPhoto()            
		self.deleteProductPhotoBt.config(state=DISABLED)
		self.clearFieldProductPhoto()
	# FIN de la gestion du module ProductPhoto --------------------------------------------------------------------------------------------------------

class ProductItemGUI(Toplevel):
	def __init__(self, parent=None, balloon=None, field=None, index=None, listObject=None, path=None, log=None):
		Toplevel.__init__(self, parent)
		self.parent=parent
		self.grab_set()
		self.transient(self.master)
		self.resizable(width=False, height=False)
		self.title(u"Articles associés")
		self.balloon=balloon
		self.imgSave=PhotoImage(file="img/save_icon.gif")
		self.imgDelete=PhotoImage(file="img/delete_icon.gif")
		self.imgSearch=PhotoImage(file="img/search_icon.gif")
		self.field=field
		self.index=index
		self.listObject=listObject
		self.path=path
		self.log=log
		# Afficher un icon personnalisé
		try:
			if os.name =="posix":
				img = PhotoImage(file=self.path+"/icons/Product-icon.gif")
				self.tk.call("wm", "iconphoto", self._w, img)
			else:
				self.iconbitmap(default=self.path+"/icons/Product-icon.gif")
		except TclError:
			self.log.warning("Le window manager ne supporte pas l'icône que je veux lui mettre...")
		self.log.info("\tProductItemGUI\tStart")
		self.makeProductItem()

	# DEBUT de la gestion du module ProductItem ------------------------------------------------------------------------------------------------------------------
	def clearFieldProductItem(self):
		# Mise a zéro des champs
		self.productItemValues[1].set("")
		self.selectedItemPI=[Item,]
		# Affichage du nombre d'Article rattaché à ce produit
		result = ProductItem.select(ProductItem.q.product==self.listObject[self.index])
		count=0
		for row in result:
			count+=1
		if count < 2:
			self.field.set(str(count)+" Article")
		else:
			self.field.set(str(count)+" Articles")

	def selectProductItem(self, event):
		if self.listProductItem.get(0)!="":
			result = ProductItem.select(ProductItem.q.id==self.idListProductItem[int(self.listProductItem.curselection()[0])])
			for row in result:
				self.selectedProductItem = row
			self.selectedItemPI=self.selectedProductItem.item
			if self.selectedProductItem.item != None:self.productItemValues[1].set(self.selectedProductItem.item)
			# activation du bouton supprimer
			self.deleteProductItemBt.config(state=NORMAL)

	def searchProductItem(self, event=None):
		self.listProductItem.delete(0,END)
		self.idListProductItem = []
		result = ProductItem.select(ProductItem.q.product==self.listObject[self.index],orderBy=ProductItem.q.id)
		for row in result:
			self.listProductItem.insert(END, str(row.id)+" - "+str(row.item))
			self.idListProductItem.append(row.id)

	def makeProductItem(self):
		leftFrame = Frame(self)
		Label(leftFrame, text=u"Fiche Article associé").pack(side=TOP, fill=X)
		productItemLabels = (u"Produit", u"Article")
		self.productItemValues = [StringVar(),StringVar()]
		count = 0
		for name in productItemLabels:
			f = Frame(leftFrame)
			Label(f, width=12, text=name, anchor=W).pack(side=LEFT)
			if count == 0: # Séjour
				Entry(f, textvariable=self.productItemValues[count], width=24, state=DISABLED, bd=0, disabledforeground="black").pack(side=LEFT, fill=X)
			else: # Item
				Entry(f, textvariable=self.productItemValues[count], width=21, state=DISABLED, bd=0, disabledforeground="black").pack(side=LEFT, fill=X)
				myItem=Button(f,  image=self.imgSearch, command=lambda x=self.productItemValues[count]:self.ctrlListItem(x), padx=4, pady=1)
				myItem.pack(side=RIGHT)
				self.balloon.bind(myItem, u"Choisir un Article")
			f.pack(side=TOP, fill=X)
			count += 1
		# Boutons enregistrement (new ou modify) et suppression
		s = Frame(leftFrame) 
		self.saveProductItemBt=Button(s, image=self.imgSave, command=self.createProductItem)
		self.saveProductItemBt.bind("<Return>", self.createProductItem)
		self.saveProductItemBt.pack(side=LEFT)
		self.balloon.bind(self.saveProductItemBt, u"Enregistrer")
		self.deleteProductItemBt=Button(s, image=self.imgDelete, command=self.deleteProductItem, state=DISABLED)
		self.deleteProductItemBt.bind("<Return>", self.deleteProductItem)
		self.deleteProductItemBt.pack(side=LEFT)
		self.balloon.bind(self.deleteProductItemBt, u"Supprimer")
		s.pack(side=TOP, fill=X)
		# Liste des Articles Choisi (présentation colonne de droite)
		Label(leftFrame, text=u"Liste des Articles liés").pack(side=TOP, fill=X)
		s = Frame(leftFrame) 
		scrollbar = Scrollbar(s)
		scrollbar.pack(side=RIGHT, fill=Y)
		self.listProductItem = Listbox(s)
		self.listProductItem.config(yscrollcommand=scrollbar.set, width=40, selectmode=SINGLE, height=10)
		self.listProductItem.bind("<ButtonRelease-1>",self.selectProductItem)
		scrollbar.config(command=self.listProductItem.yview)
		self.listProductItem.pack(side=TOP, fill=X)
		self.balloon.bind(self.listProductItem, u"Séléctionner un Article Choisi\npour le visualiser ou la modifier.")
		s.pack(side=TOP, fill=X)
		leftFrame.pack(side=LEFT, fill=X)
		# Initialisation
		self.productItemValues[0].set("ID:"+str(self.listObject[self.index].id)+" "+self.listObject[self.index].designation)
		self.selectedItemPI=[Item,]
		self.searchProductItem()

	def ctrlListItem(self,field):
		ItemListGUI(balloon=self.balloon, field=field, index=0, listObject=self.selectedItemPI, log=self.log, path=self.path)

	def verifyProductItem(self):
		if self.productItemValues[1].get() == "":
			showerror(u"Erreur de saisie", u"Le champ Article est obligatoire !\nMerci de le compléter.")
			return False
		else:
			return True

	def createProductItem(self, event=None):
		if self.verifyProductItem():
			if  self.deleteProductItemBt.config()["state"][4] == "normal":
				self.modifyProductItem()
			else:
				if askyesno(u"Enregistrement", u"Souhaitez-vous enregistrer %s comme un nouvel Article lié au produit ?\n" % self.productItemValues[1].get()):
					ProductItem(product=self.listObject[self.index],
						item=self.selectedItemPI[0],
						createDate=datetime.datetime.now()
					)
					self.searchProductItem()
				self.clearFieldProductItem()

	def modifyProductItem(self, event=None): 
		if askyesno(u"Modifier", u"Souhaitez-vous modifier l'Article lié au produit %s ?" % self.selectedProductItem.item):
			self.selectedProductItem.item=self.selectedItemPI[0]   
			self.searchProductItem()
		self.deleteProductItemBt.config(state=DISABLED)
		self.clearFieldProductItem()

	def deleteProductItem(self, event=None): 
		if askyesno(u"Suppression", u"Souhaitez-vous supprimer la liaison a ce produit pour l'Article %s ?\nCette opération est irréversible !" % self.selectedProductItem.item):
			ProductItem.delete(self.selectedProductItem.id)
			self.searchProductItem()            
		self.deleteProductItemBt.config(state=DISABLED)
		self.clearFieldProductItem()
	# FIN de la gestion du module ProductItem --------------------------------------------------------------------------------------------------------------